package com.codemes.happylist.views.loading;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.codemes.happylist.CodemesToolMain;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import lombok.extern.slf4j.Slf4j;

import java.net.URL;
import java.util.concurrent.*;

@Slf4j
public class CodemesLoading {

    /** 当前loading组件 */
    private Stage $this;
    /** 所属组件 */
    private Stage parent;
    /** 显示时间  */
    private Integer timeout;
    private static final Integer DEFAULT_TIMEOUT = 60;

    /** 显示提示内容*/
    private String msg;
    private static final String DEFAULT_MSG = "loading";

    private double transparency = 0.3;

    private final ScheduledExecutorService scheduler;

    private final ThreadPoolExecutor taskExecutor;

    private static final String BOOTSTRAPFX_STYLE_CSS = "/css/BootStrapFx.css";

    ScheduledFuture<?> scheduledFuture;

    Task<?> task;

    CodemesLoading(){
        scheduler = Executors.newScheduledThreadPool(4,
                new ThreadFactoryBuilder()
                        .setNamePrefix("Codemesloading-close-")
                        .setDaemon(true)
                        .build());
        taskExecutor = new ThreadPoolExecutor(2,2,30,TimeUnit.SECONDS,
                new SynchronousQueue<>(),new ThreadFactoryBuilder()
                .setNamePrefix("CodemesTask-run-")
                .setDaemon(true)
                .build()
        );
    }

    /**
     * 创建loading
     * @param parent
     *      所属窗口
     * @param msg
     *      显示的提示信息，默认为 loading
     * @param timeout
     *      显示时长，默认60秒
     * @param transparency
     *      透明度
     * @param task
     *      要执行的任务
     * @return 返回loading对象
     */
    public static CodemesLoading of(Stage parent, String msg, Integer timeout, Double transparency, Task<?> task){
        CodemesLoading loading = new CodemesLoading();
        loading.msg = msg==null?DEFAULT_MSG:msg;
        loading.timeout = timeout==null?DEFAULT_TIMEOUT:timeout;
        if(null!=transparency){
            loading.transparency = transparency;
        }
        loading.task=task;
        loading.parent=parent;
        loading.init();
        return loading;
    }
    /**
     * 创建loading
     * @param parent
     *      所属窗口
     * @param msg
     *      显示的提示信息，默认为 loading
     * @param timeout
     *      显示时长，默认60秒
     * @param transparency
     *      透明度
     * @return 返回loading对象
     */
    public static CodemesLoading of(Stage parent,String msg,Integer timeout,Double transparency){
        return of(parent,msg,timeout,transparency,null);
    }
    /**
     * 创建loading
     * @param parent
     *      所属窗口
     * @param msg
     *      显示的提示信息，默认为 loading
     * @param timeout
     *      显示时长，默认60秒
     * @param task
     *      要执行的任务
     * @return 返回loading对象
     */
    public static CodemesLoading of(Stage parent,String msg,Integer timeout, Task<?> task){
        return of(parent,msg,timeout,null,task);
    }
    /**
     * 创建loading
     * @param parent
     *      所属窗口
     * @param msg
     *      显示的提示信息，默认为 loading
     * @param transparency
     *      透明度
     * @param task
     *      要执行的任务
     * @return 返回loading对象
     */
    public static CodemesLoading of(Stage parent,String msg,Double transparency,Task<?> task){
        return of(parent,msg,null,transparency,task);
    }
    /**
     * 创建loading
     * @param parent
     *      所属窗口
     * @param msg
     *      显示的提示信息，默认为 loading
     * @param timeout
     *      显示时长，默认60秒
     * @return 返回loading对象
     */
    public static CodemesLoading of(Stage parent,String msg,Integer timeout){
        return of(parent,msg,timeout,null,null);
    }
    /**
     * 创建loading
     * @param parent
     *      所属窗口
     * @param msg
     *      显示的提示信息，默认为 loading
     * @param transparency
     *      透明度
     * @return 返回loading对象
     */
    public static CodemesLoading of(Stage parent,String msg,Double transparency){
        return of(parent,msg,null,transparency);
    }

    private void init() {
        $this = new Stage();
        $this.initOwner(parent);
        // 设置显示loading的样式
        // 设置loading没有任何装饰
        $this.initStyle(StageStyle.UNDECORATED);
        // 设置背景透明
        $this.initStyle(StageStyle.TRANSPARENT);
        $this.initModality(Modality.APPLICATION_MODAL);

        BorderPane pane = new BorderPane();
        pane.setStyle("-fx-background-color: rgba(0,0,0,0.5);");

        VBox vBox = new VBox();
        vBox.setSpacing(10);
        vBox.setAlignment(Pos.CENTER);
        pane.setCenter(vBox);

        Button btnClose = new Button("关闭");
        btnClose.setOnAction(event -> close());
        btnClose.getStyleClass().addAll("btn-info");

        ProgressIndicator progressIndicator = new ProgressIndicator();
        progressIndicator.setProgress(-1F);
        if(null!=task){
            progressIndicator.progressProperty().bind(task.progressProperty());
        }

        Label lblMsg = new Label();
        lblMsg.setText(msg);
        lblMsg.setTextFill(Color.CHARTREUSE);
        vBox.getChildren().addAll(btnClose,progressIndicator,lblMsg);

        Scene scene = new Scene(pane);
        scene.setFill(null);
        $this.setScene(scene);

        double sceneHeight = parent.getScene().getHeight();
        double windowHeight = parent.getHeight();
        double x = parent.getX();
        double y = parent.getY()+(windowHeight-sceneHeight);
        $this.setX(x);
        $this.setY(y);

        $this.setHeight(sceneHeight);
        $this.setWidth(parent.getWidth());

        // 定时关闭loading窗口
        log.info("定时关闭loading窗口 ->{}",timeout);
        scheduledFuture = scheduler.schedule(() -> Platform.runLater(this::close), timeout, TimeUnit.SECONDS);
        if(null!=task){
            task.setOnSucceeded(e -> close());
        }

        URL bootStrapFxStyleUrl = CodemesToolMain.class.getResource(BOOTSTRAPFX_STYLE_CSS);
        ObservableList<String> stylesheets = $this.getScene().getStylesheets();
        log.info("load bootstrap css ->{}",bootStrapFxStyleUrl.toExternalForm());
        stylesheets.add(bootStrapFxStyleUrl.toExternalForm());
    }

    public void show(){
        log.info("显示当前loading 窗口 -->{}",Thread.currentThread().getName());
        $this.show();
        if(null!=task){
            log.info("任务信息不为空，执行任务>>{}",task);
            scheduler.schedule(task, 1, TimeUnit.SECONDS);
        }
    }

    public void close(){
        // 去掉定时器
        scheduledFuture.cancel(false);
        log.info("关闭当前loading 窗口 -->{}",Thread.currentThread().getName());
        $this.close();
    }

}
